

<script lang="ts" setup>
import { ref,onMounted,watch,computed } from 'vue';

import { Modal, Button, Tabs, message, Upload ,List, Radio, Spin} from 'ant-design-vue';
import { getAssets } from '#/api/system';

import Icon from '#/components/Icons';
interface AssetItem {
  id: number;
  file_path: string;
  filename: string;
}


const loading = ref(false);
const assets = ref<AssetItem[]>([]);
const fileListinit = ref([]);  // 用来存储上传的文件列表
const page = ref(1); // 当前页码
const limit = 30; // 每页数量
const finished = ref(false); // 是否加载完了全部数据

const fetchAssets = async () => {

  if (loading.value || finished.value) return;

  loading.value = true;
  try {
     const params = {
      page: page.value,
      limit,
      keyword: searchKeyword.value.trim(),
      file_type: props.type,
      sort_order: sortOrder.value,
      //file_types:props.type
    };

    const res = await getAssets(params); // 你的接口需支持分页
    if (res.code === 1 && res.data && Array.isArray(res.data.list)) {
      if (res.data.list.length < limit) {
        finished.value = true;
      }
      if (res.data.list.length > 0) {
        assets.value.push(...res.data.list);
        page.value += 1;
      }
      console.log(assets.value)

    } else {
      message.error('获取图库失败');
    }
  } catch (error) {
    message.error('接口请求出错');
  } finally {
    loading.value = false;
  }
};



const activeTab = ref('upload');


const selectedIds = ref<number[]>([]);
const selectedIdSet = computed(() => new Set(selectedIds.value));


const selectedItem = ref<any | null>(null);





function selectGalleryItem(item: any, event: MouseEvent) {

  if (event.ctrlKey) {
    if(props.multiple){
       // 多选
        const index = selectedIds.value.indexOf(item.id);
        if (index === -1) {
          selectedIds.value.push(item.id);
        } else {
          selectedIds.value.splice(index, 1); // 取消选中
        }
    }else{
      selectedIds.value = [item.id];
      selectedItem.value =[item];
    }
   
  } else {
  
    // 单选
    selectedIds.value = [item.id];
    selectedItem.value = [item]; // ✅ 这里你原本就设置了

  }
  
}



// 拼接图片URL
const getImageUrl = (path: string) => {
  // 根据你的接口或者静态资源路径调整
  return `/api/uploads/${path}`;
};



const visible = ref(false);
const mode = ref<'upload' | 'gallery'>('upload');

const showModal = () => {
  visible.value = true;
};




const handleCancel = () => {
  visible.value = false;
};




const handleTabChange = (key: string) => {
 
  activeTab.value = key;
  if (key === 'gallery') {
    if (assets.value.length === 0) {
      page.value = 1;
      assets.value = [];
      fetchAssets();
    }
  }
};





import type { UploadChangeParam, UploadProps } from 'ant-design-vue';

import { useAccessStore } from '@vben/stores';
import { isString } from '@vben/utils';


import { baseUrlApi } from '#/api/request';
import { postUpload } from '#/api/system';
import { usePreferencesStore } from '#/store';
import { formatFilePath } from '#/utils';





defineOptions({
  name: 'CustomUpload',
});



const props = withDefaults(
  defineProps<{
    modelValue?: any;
    multiple?: boolean;
    ignoreWatch?:boolean;
    name?: string;
    returnstr?: boolean;
    showbox?: boolean;
    displayMode?: 'grid' | 'list'; 
    type?: 'audio' | 'file' | 'image' | 'photo' | 'video';
    ucClass?: string;
    tips:'',
  }>(),
  {
    ignoreWatch:false,
    multiple: false,
    showbox: true,
    returnstr: false,
    displayMode:'grid',
    type: 'image',
    modelValue: [],
    name: '',
    ucClass: 'upload-content',
    tips:'',
  },
);

const emit = defineEmits<{
  (e: 'update:modelValue', data: any): void;
}>();

const accessStore = useAccessStore();
const uploadRef = ref<UploadProps>();
const uploadRef1 = ref<UploadProps>();
const ignoreWatch = ref(false);

const state: any = reactive({
  accept: '.jpg,.jpeg,.png,.gif,.bmp4',
  limit: 50,
  size: 1,
  action: `${baseUrlApi('/user/upload/one')}`,
  headers: {},
  fileList: [],
  picture: 'picture',
  data: {},
  extensions: '',
  imgList: [],
  toWebp:true,
  uploadedFiles: [], // 新增字段来跟踪已上传的文件
});
const listtype: any = ref('picture-card');
const imageUrl = ref('');



function getFileExtension(filename: string): string {
  const parts = filename.split('.');
  return parts.length > 1 ? parts.pop()!.toLowerCase() : '';
}

function isStringArray(value) {
  return Array.isArray(value) && typeof value[0] === 'string';
}

function isObjectArrayWithUrl(value) {
  return Array.isArray(value) && typeof value[0] === 'object' && value[0] !== null && 'url' in value[0];
}



watch(
  () => props.modelValue,
  (value) => {
    if (ignoreWatch.value){

       return;
    }

    // 清空旧状态
    state.uploadedFiles = [];
    state.fileList = [];
    imageUrl.value = '';

    if (!value) return;          // 空值直接结束

    // ⬇️ 为了兼容两种数据结构做几个工具函数
    const getUrl = (item: any) =>
      isString(item) ? item : item?.url || '';
    const getId = (item: any) =>
      isString(item) ? undefined : item?.id;
      if(Array.isArray(value)){

            value.forEach((item, index) => {
          
                const url = formatFilePath(getUrl(item.url));
                if (!url) return;        // 跳过空 url

                const name = url.split('/').pop() || '';
                const ext  = getFileExtension(name);
        
                state.fileList.push({
                  uid: `${index}`,
                  name,
                  status: 'done',
                  url,
                  path: url,
                  ext,
                  id: getId(item),      // ⬅️ 新增 id 字段，旧格式时为 undefined
                  cover: [
                    {
                    url:item.cover,

                  }
                  ]
                });
                state.uploadedFiles.push({
                  url:item.url,
                  id:url.id
                });
              });

      }
            


    // ========= 多图 =========
    // if (props.multiple && Array.isArray(value)) {
    //   if (isStringArray(value)) {
    //        value.forEach((item, index) => {
    //             const url = formatFilePath(getUrl(item));
    //             if (!url) return;        // 跳过空 url

    //             const name = url.split('/').pop() || '';
    //             const ext  = getFileExtension(name);
        
    //             state.fileList.push({
    //               uid: `${index}`,
    //               name,
    //               status: 'done',
    //               url,
    //               path: url,
    //               ext,
    //               id: getId(item),      // ⬅️ 新增 id 字段，旧格式时为 undefined
    //               cover: []
    //             });

              
    //             state.uploadedFiles.push(item);
    //           });
    //   }else if (isObjectArrayWithUrl(value)){
      
    //          value.forEach((item, index) => {
    //             const url = formatFilePath(getUrl(item.url));
    //             if (!url) return;        // 跳过空 url

    //             const name = url.split('/').pop() || '';
    //             const ext  = getFileExtension(name);
        
    //             state.fileList.push({
    //               uid: `${index}`,
    //               name,
    //               status: 'done',
    //               url,
    //               path: url,
    //               ext,
    //               id: getId(item),      // ⬅️ 新增 id 字段，旧格式时为 undefined
    //               cover: [
    //                 {
    //                 url:item.cover,

    //               }
    //               ]
    //             });
    //             state.uploadedFiles.push({
    //               url:item.url,
    //               id:url.id
    //             });
    //           });

    //   }
            
    //     return;
    // }
    // console.log(value);
    // console.log(isObjectArrayWithUrl(value))
    // // ========= 单图 =========
    // if (!props.multiple && (isString(value)  || isObjectArrayWithUrl(value))) {
    
    //     if (isString(value)) {
    //              const url = formatFilePath(getUrl(value));
    //               if (!url) return;

    //               const name = url.split('/').pop() || '';
    //               const ext  = getFileExtension(name);

    //               state.fileList.push({
    //                 uid: '0',
    //                 name,
    //                 status: 'done',
    //                 url,
    //                 path: url,
    //                 ext,
    //                 id: getId(value),
    //                 cover: []
    //               });

    //               imageUrl.value = url;      // 兼容旧代码
    //               state.uploadedFiles.push(value);
    //     }   else if (isObjectArrayWithUrl(value)){
    //                  value.forEach((item, index) => {
    //                 const url = formatFilePath(getUrl(item.url));
    //                 if (!url) return;        // 跳过空 url

    //                 const name = url.split('/').pop() || '';
    //                 const ext  = getFileExtension(name);
            
    //                 state.fileList.push({
    //                   uid: `${index}`,
    //                   name,
    //                   status: 'done',
    //                   url,
    //                   path: url,
    //                   ext,
    //                   id: getId(item),      // ⬅️ 新增 id 字段，旧格式时为 undefined
    //                   cover: [
    //                     {
    //                     url:item.cover,

    //                   }
    //                   ]
    //                 });
    //                 state.uploadedFiles.push({
    //                   url:item.url,
    //                   id:url.id
    //                 });
    //               });
    //     }
    
    // }
  },
  { deep: true, immediate: true }
);


// watch(
//   () => props.modelValue,
//   (value) => {
//     if(ignoreWatch.value)return;
//     state.uploadedFiles = [];
//     state.fileList = [];

//     if (!value) {
//       imageUrl.value = '';
//       return ''; 
//     }


//    if (props.multiple && Array.isArray(value)) {
  
//       // 多图
//       value.forEach((element, index) => {
//           if (isString(element)) {
//             const name = element.split('/').pop() || '';
//             const ext = getFileExtension(name);

//             state.fileList.push({
//               uid: `${index}`,
//               name,
//               status: 'done',
//               url: formatFilePath(element),
//               path: element,
//               ext, // 添加文件扩展名字段
//               cover:[
//                 // {
//                 //   uid: '0',
//                 //   name:'',
//                 //   status: 'done',
//                 //   url: '',
//                 //   path: '',
//                 // }
//               ]
//             });
//             state.uploadedFiles.push(element);
//           }
//         });
//          imageUrl.value = '';
//     } else if (!props.multiple && isString(value)) {
//         // 单图也放到 fileList 中
//         const url = formatFilePath(value);
//         const name = value.split('/').pop() || '';
//         const ext = getFileExtension(name);

//         state.fileList.push({
//           uid: '0',
//           name,
//           status: 'done',
//           url,
//           path: value,
//           ext, 
//           cover:[
//                 // {
//                 //   uid: '0',
//                 //   name:"",
//                 //   status: 'done',
//                 //   url: '',
//                 //   path: '',
//                 // }
//               ]
//         });
//         imageUrl.value = url; // 兼容旧代码，单图也赋值imageUrl
//         state.uploadedFiles.push(value);
//     } else {
//        imageUrl.value = '';
//     }

//   },
//   {
//     deep: true,
//     immediate: true,
//   }
// );



const onConfirm = () => {
  if (props.multiple) {
    let oldFiles: { id: number; url: string }[] = [];

    if (Array.isArray(props.modelValue)) {
      oldFiles = [...props.modelValue]; // 保留旧值
    }

    // 获取当前新选择的文件
    const selectedFiles = assets.value.filter((item) =>
      selectedIds.value.includes(item.id)
    );

    const newFiles = selectedFiles.map((item) => ({
      id: item.id,
      url: item.file_path,
    }));

    // 合并去重（根据 id 去重）
    const mergedMap = new Map<number, { id: number; url: string }>();
    [...oldFiles, ...newFiles].forEach(file => {
      mergedMap.set(file.id, file); // id 相同会被覆盖
    });

    const mergedList = Array.from(mergedMap.values());

    emit('update:modelValue', mergedList);
  } else {
    // 单图模式
    const selected = assets.value.find((item) => item.id === selectedIds.value[0]);
    if (selected) {
      emit('update:modelValue', [{ id: selected.id, url: selected.file_path }]);
    } else {
      emit('update:modelValue', [{ id: 0, url: '' }]);
    }
  }

  visible.value = false;
};


// const onConfirm = () => {
//   let oldFiles: string[] = [];
//   // 先处理旧值
//   if (props.multiple) {
//     if (Array.isArray(props.modelValue)) {
//       oldFiles = [...props.modelValue]; // 多图时保留原值
//     } else if (typeof props.modelValue === 'string' && props.modelValue !== '') {
//       oldFiles = [props.modelValue];
//     }

//     // 获取当前新选择的文件
//     const selectedFiles = assets.value.filter((item) =>
//       selectedIds.value.includes(item.id)
//     );
//     const newPaths = selectedFiles.map((item) => item.file_path);

//     // 合并：防止重复
//     const mergedPaths = Array.from(new Set([...oldFiles, ...newPaths]));

//     // 发出更新
//     emit('update:modelValue', props.returnstr ? mergedPaths.join(',') : mergedPaths);
//   } else {
//     // 单图模式
//     const selected = assets.value.find((item) => item.id === selectedIds.value[0]);
//     emit('update:modelValue', selected?.file_path || '');
//   }

//   visible.value = false;
// };


function formatFileExtensions(fileFormats: string): string {
  const formatsArray = fileFormats
    .split(',')
    .map((format) => `.${format.trim()}`);
  return formatsArray.join(',');
}
const uploadSetting = async () => {
  const fileType = props.type === 'photo' ? 'image' : props.type;
  if (fileType !== 'image') {
    state.uclass = '';
    listtype.value = 'text';
  }

  const setting = await usePreferencesStore().getUploadSetting();
  const fileSetting = setting.file_types[fileType];
  const accept = formatFileExtensions(fileSetting.extensions);

  state.size = fileSetting.upload_max_filesize / 1024;
  state.accept = accept;
};

const beforeUpload: UploadProps['beforeUpload'] = (rawFile: any) => {
  if (rawFile.size / 1024 / 1024 > state.size) {
    message.error(`文件大小必须小于${state.size}!`);
    return false;
  }

  return true;
};

const handleScroll = (event) => {
  const el = event.target;
  if (el.scrollHeight - el.scrollTop <= el.clientHeight + 10) {
    fetchAssets();
  }
};




const httpRequest = async (options: any) => {
  options.data.filetype = props.type;
  options.data.toWebp = state.toWebp
  try {

      const { data } = await postUpload(options);

        options.onSuccess(data, options.file);



    if (props.multiple) {
      const newFile = {
        name: data.filename,
        path: data.filepath,
        url: data.url,
      };
      state.uploadedFiles.push(newFile.path);
      const existingFileIndex = state.fileList.findIndex(
        (item: any) => item.path === newFile.path,
      );
      if (existingFileIndex !== -1) {
        state.fileList.splice(existingFileIndex, 1);
        return;
      }
  
      state.fileList.push(newFile);
      // if (state.uploadedFiles.length === state.fileList.length) {
      //   emit('update:modelValue', state.uploadedFiles);
      // }
    } else {
      imageUrl.value = data.url;
      // emit('update:modelValue', data.filepath);
    }
  } catch {
    // onError(error);
  }
};


const handleRemove: UploadProps['onRemove'] = (uploadFile: any) => {
  if (state.uploadedFiles.length > 0) {
    const existingFileIndex = state.uploadedFiles.indexOf(uploadFile.path);
    if (existingFileIndex !== -1) {
      state.uploadedFiles.splice(existingFileIndex, 1);
    }
    // emit('update:modelValue', state.uploadedFiles);
  }
};


function handleRemove1(file) {

  // 1. 删除 fileList 中的文件
  const index = state.fileList.findIndex(item => item.uid === file.uid);
  if (index !== -1) {
    state.fileList.splice(index, 1);
  }

  // 2. 删除 uploadedFiles 中的文件
  const pathToDelete = file.path;

  if (props.multiple) {
    // 多图，modelValue 是数组，元素为对象 { id, url }
    const updated = state.uploadedFiles.filter(item => {
      const url = isString(item) ? item : item?.url;
      return url !== pathToDelete;
    });
    state.uploadedFiles = updated;
    emit('update:modelValue', updated);
  } else {
    // 单图，直接清空
    state.uploadedFiles = [];
    emit('update:modelValue', [{ id: 0, url: '' }]); // 或直接 emit('', '') 视你是否需要清空为 null 或空对象
  }
}


function handleRemove2(removedFile,index) {
  // removedFile 是被删除的文件对象，带 uid 属性
  // 这里要注意，removedFile 只是单个文件，不是 file，得找到对应的 file
  // 需要传入 file 和被删文件才能操作，或者通过事件参数

  // 假设你有 index，能拿到对应的 file
  const fileItem = state.fileList[index];  // 这里要根据上下文拿索引

  const coverIndex = fileItem.cover.findIndex(item => item.uid === removedFile.uid);
  
  if (coverIndex !== -1) {
    fileItem.cover.splice(coverIndex, 1);
  }
}


const handleUploadChange = (info: UploadChangeParam) => {
  // 手动判断并设置上传成功状态

  if (info.file.response?.code === 1) {
    info.file.status = 'done'; // ✅ 强制标记为 done
  }

  const { status } = info.file;

  if (status === 'done') {
      activeTab.value = 'gallery';
    
      console.log(info.file.response);
      const uploadedFilename = info.file.response.filename; // 用 response 的 filename 更保险
      message.success(info.file.response.filename);
      setTimeout(async () => {
        //初始化之后重新获取数据
        finished.value=false;
        page.value=1;
        assets.value=[];
        await fetchAssets();

        const uploaded = assets.value.find(img => img.filename === uploadedFilename);
        if (uploaded) {
          if (props.multiple && !selectedIds.value.includes(uploaded.id)) {
            selectedIds.value.push(uploaded.id);
          } else {
            selectedIds.value = [uploaded.id];
          }
        }
      }, 300);
  } else if (status === 'error') {
    message.error(`${info.file.name} 文件上传失败`);
  }
};



function handleUploadChange11(info, index) {
  // 手动判断并设置上传成功状态
  
  if (info.file.response?.code === 1) {
    info.file.status = 'done'; // ✅ 强制标记为 done
  }



};


const httpRequest1 = async (options: any, index: number) => {
  options.data.filetype = props.type;
  ignoreWatch.value = true;
  

  try {
    const { data } = await postUpload(options);

    options.onSuccess(data, options.file);

    if (state.fileList[index]) {
      state.fileList[index].cover = [
        {
          name: data.filename,
          id: 0,
          url: data.url,
        },
      ];
    }
    let arrs =[];
    state.fileList.forEach((item)=>{
           arrs.push({
               id:item.id,
               url:item.url
           })
    })

    emit('update:modelValue', arrs);

  } catch (error) {
    console.error('上传失败', error);
  }
};



onMounted(() => {
  const token = accessStore.accessToken;
  state.headers['XX-Token'] = token;
  state.headers.Authorization = token;
  state.headers['XX-Device-Type'] = 'web';
  uploadSetting();
});






const searchKeyword = ref('');
const searchType = ref('');
const sortOrder = ref<'asc' | 'desc'>('desc');

const originalAssets = ref<[]>([]);
const assets1 = ref<[]>([]);


// 关键：调用搜索时调用此函数
function resetAndSearch() {
  page.value = 1;          // 重置页码
  finished.value = false;  // 重置完成标志
  assets.value = [];       // 清空已有数据
  fetchAssets();
}

// 排序切换时
function toggleSortOrder() {
  sortOrder.value = sortOrder.value === 'desc' ? 'asc' : 'desc';
  resetAndSearch();
}

// 搜索按钮调用
function onSearchClick() {
  resetAndSearch();
}
function onImageError(event) {

  event.target.src = 'http://127.0.0.1/static/images/defult.jpg'; // 替换为你的默认图片路径
}




</script>

<template>





  <div>
    <div v-if="displayMode=='grid'">
       <div class='flex1' >
              <Upload 
                  :file-list="state.fileList"
                  list-type="picture-card"
                  :show-upload-list="{ showPreviewIcon: true, showRemoveIcon: true }"
                  :before-upload="() => false"
                  @preview="handlePreview"
                  @remove="handleRemove1"
                  show-upload-button="false" style="width:auto"></Upload>
                    <span v-if="props.multiple || state.fileList.length === 0" @click="showModal">
                      <div class="upload-init-me">
                        <Icon icon="ri:add-line" />
                        <div class="u">Upload</div>
                      </div>
                    </span>   
         </div>
          <p class="mt-2 text-sm text-red-600" style="width:102px；word-wrap: break-word;overflow-wrap: break-word;">
                {{ props.tips }}
          </p>
    </div>
     <div v-else-if="displayMode=='list'">
      
        <div v-if="state.fileList.length>0">
               <div v-for="(file, index) in state.fileList" :key="file.uid" class="flex-center" style="gap:3rem;height:3rem;border-bottom:1px solid #ccc;height:100px;width:300px;justify-content: start;">
                     <div class="file-preview">
                        <img 
                          v-if="file.type?.startsWith('image/')" 
                          :src="file.url || file.thumbUrl" 
                          class="file-thumbnail"
                        >
                        
                        <img style="width:60px !important;height:60px !important" :src="file.url">
                    </div>  
                    <div  v-if="!['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(file.ext)" size="small">
                       <div class="flex flex-col">

                          <Upload  class="uploadRef1-1 flex1"
                                    
                                       ref="uploadRef1"
                                      :file-list="file.cover"
                                      :accept="state.accept"
                                      :action="state.action"
                                      :before-upload="beforeUpload"
                                      :class="ucClass"
                                      :custom-request="(options) => httpRequest1(options, index)"
                                       :data="{ ...state.data, cover: 1 ,img_id:file.id}"
                                      :headers="state.headers"
                                      :limit="state.limit"
                                      :multiple="false"
                                      :ignoreWatch="true"
                                      listType='picture-card'
                                      name="file"
                                       @remove="(removedFile) => handleRemove2(removedFile, index)"
                                      @change="(info) => handleUploadChange11(info, index)"
                         >
                                        <template v-if="!file.cover.url || file.cover.length === 0">
                                          设置封面
                                        </template>
                                    
                                    </Upload>
                                
                      </div>

                    </div>
                      <Button  type="text"  danger    size="small"    @click="handleRemove1(file)" >  <Icon icon="ri:delete-bin-line" /> </Button>
              </div>
        </div>
        <div >
          <Upload 
            list-type="picture-card"
            :show-upload-list="{ showPreviewIcon: true, showRemoveIcon: true }"
            :before-upload="() => false"
            @preview="handlePreview"
            @remove="handleRemove1"
            show-upload-button="false" style="width:auto"></Upload>
            <span v-if="props.multiple || state.fileList.length === 0" @click="showModal">
            <div class="upload-init-me">
              <Icon icon="ri:add-line" />
              <div class="u">Upload</div>
            </div>
          </span>
        </div>
     </div>
 




    <!-- 使用组件名 Modal, Tabs 代替 a-modal, a-tabs -->
  <Modal
    :visible="visible"
    title="上传图片"
    @cancel="handleCancel"
    confirmText="确认"
    cancelText="取消"
    :fullscreenButton="true"
    :draggable="true"
    :destroyOnClose="true"
    :width="900"
    @ok="onConfirm"
  > 
    <Tabs :activeKey="activeTab" @change="handleTabChange">
      <Tabs.TabPane key="upload" tab="本地上传">
        


        <div class="flex flex-col">
              <Upload
                ref="uploadRef"
                :accept="state.accept"
                :action="state.action"
                :before-upload="beforeUpload"
                :class="ucClass"
                :custom-request="httpRequest"
                :data="state.data"
                :headers="state.headers"
                :limit="state.limit"
                :show-upload-list="true" 
                :list-type="listtype"
                :multiple="multiple"
               
                name="file"
                @change="handleUploadChange"
              >
                <Icon icon="ri:add-line" />
              </Upload>
               <!-- 是否转换为 WebP -->
              <label class="mt-2 text-sm text-gray-800 flex items-center">
                <input type="checkbox" v-model="state.toWebp" class="mr-1" />
                转换为 WebP 格式
              </label>
              <p class="mt-2 text-sm text-red-600">
                小于{{ state.size }}MB的{{ state.accept }}文件
              </p>

            


            </div>



      </Tabs.TabPane>
      <Tabs.TabPane key="gallery" tab="系统图库">
      <!-- 搜索和排序栏 -->
        <div class="flex items-center flex-wrap gap-4 mb-4 p-3 bg-gray-100 rounded border">
          <!-- 文件名搜索 -->
          <input v-model="searchKeyword" type="text" placeholder="搜索文件名"
                class="px-3 py-1 border rounded w-48" />

          <!-- 类型筛选 -->
          <select v-model="searchType" v-if="false" class="px-3 py-1 border rounded w-32">
            <option value="">全部类型</option>
            <option value="jpg">JPG</option>
            <option value="png">PNG</option>
            <option value="gif">GIF</option>
            <option value="mp4">MP4</option>
          </select>

          <!-- 排序按钮 -->
          <button @click="toggleSortOrder"
                  class="flex items-center gap-1 px-3 py-1 border rounded bg-white hover:bg-gray-200">
            <svg v-if="sortOrder === 'desc'" xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none"
                viewBox="0 0 24 24" stroke="currentColor">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                    d="M5 15l7-7 7 7" />
            </svg>
            <svg v-else xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none"
                viewBox="0 0 24 24" stroke="currentColor">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                    d="M19 9l-7 7-7-7" />
            </svg>
            <span>{{ sortOrder === 'desc' ? '最新优先' : '最旧优先' }}</span>
          </button>

          <!-- 搜索按钮 -->
          <button @click="resetAndSearch"
                  class="px-4 py-1 bg-blue-500 text-white rounded hover:bg-blue-600">
            搜索
          </button>
        </div>


      
          <div class="" @scroll="handleScroll" style="height:600px;overflow-y:scroll;">
            <List :dataSource="assets" :grid="{ gutter: 8,xs: 1,sm: 2, md: 3,lg: 4, xl: 6, xxl: 6}" bordered class="pt-2">
              <template #renderItem="{ item }">
                <List.Item>
                  <img @click="(event) => selectGalleryItem(item, event)"
                        :src="`${item.thumb}`"
                        :alt="item.filename"
                         @error="onImageError"
                        :class="['imgs_upload', { 'active-border': selectedIdSet.has(item.id) }]"/>
                  <div class="w-full text-center truncate">{{item.filename}}</div>      
                </List.Item>
              </template>
            </List>
            <div v-if="loading" class="text-center p-2">加载中...</div>
            <div v-if="finished" class="text-center p-2 text-gray-400">已全部加载</div>
          </div>

          
          <div v-if="selectedItem" class="mt-4 p-3 border rounded bg-gray-50">
          <div v-for="(file, index) in selectedItem" :key="file.id" class="mb-2 text-sm">
            <div><strong>文件名：</strong>{{ file.filename }}</div>
            <div><strong>大小：</strong>{{ (file.file_size / 1024).toFixed(2) }} KB</div>
            <div><strong>地址：</strong><a :href="file.file_path" target="_blank" class="text-blue-500 underline">{{ file.file_path }}</a></div>
          </div>
        </div>




      </Tabs.TabPane>
    </Tabs>


  
  </Modal>
  </div>

</template>



<style lang="scss" scoped>
.table-uploader {
  :deep(.ant-upload) {
    width: 40px !important;
    height: 40px !important;
  }
}
// .avatar{
//   width:100px;
//   height:100px;

// }

.imgs_upload{
    width: 100%; 
    height: 120px; 
    object-fit: contain;
    cursor: pointer;
}
.active-border {
  border: 3px solid #1890ff;
  box-sizing: border-box;
}
img{
    width: 102px;
    height: 102px;
    margin-inline-end: 8px;
    margin-bottom: 8px;
    text-align: center;
    vertical-align: top;
    background-color: rgba(50, 54, 57, 0.02);
    border: 1px dashed hsl(240 5.9% 90%);
    border-radius: 10px;
    cursor: pointer;
    transition: border-color 0.3s;
    display:flex;
    justify-content: center;
     cursor: pointer;
  
}


.gallery-list{
     height:500px;    
     overflow-y: scroll;
}
.upload-init-me{
   display: flex;
    width: 104px;
    height: 104px;
    background-color: rgb(250, 250, 250);
    cursor: pointer;
    border-width: 1px;
    border-style: dashed;
    border-color: rgb(217, 217, 217);
    border-image: initial;
    border-radius: 2px;
    transition: border-color 0.3s;
    justify-content: center;
    align-items: center;
    flex-direction: column;
}
.vxe-cell .upload-init-me{
   width: 100%;
   height: 100%;
}
.vxe-cell .upload-init-me .u{
  display: none;
}
.flex1{
  display: flex;
  justify-content: flex-start;
  align-items: center;
  word-break: break-word;
  white-space: normal;

  
}
.uploadRef1-1 {
     
}
.uploadRef1-1 {
  :deep(.ant-upload-select-picture-card) {
    width: 57px !important;
    height: 19px !important;
    font-size: 12px !important;
  }
  :deep(.ant-upload-list-item-container){
    width: 60px !important;
    height: 40px !important;
  }
}
</style>